<!-- HTML header for doxygen 1.8.11-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.11"/>
<title>i2cpwm_board: Main Page</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="styles.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectalign" style="padding-left: 0.5em;">
   <a href="./index.html"><div id="projectname">i2cpwm_board
   &#160;<span id="projectnumber">0.5.1</span>
   </div></a>
   <div id="projectbrief">ROS Package for PCA9685 based 16 channel PWM Board with I2C Interface</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.11 -->
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">i2cpwm_board Documentation</div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>Controller for I2C interfaced 16 channel PWM boards with PCA9685 chip<br />
 Bradan Lane Studio <a href="#" onclick="location.href='mai'+'lto:'+'inf'+'o@'+'bra'+'da'+'nla'+'ne'+'.co'+'m'; return false;">info@<span style="display: none;">.nosp@m.</span>brad<span style="display: none;">.nosp@m.</span>anlan<span style="display: none;">.nosp@m.</span>e.co<span style="display: none;">.nosp@m.</span>m</a><br />
 Copyright (c) 2016, Bradan Lane Studio<br />
 Licensed under GPLv3<br />
 </p><hr/>
<h1><a class="anchor" id="overview"></a>
FILE STRUCTURE AND CODE</h1>
<p>The file is broken into sections:</p><ul>
<li>private properties (all private properties have a leading underscore)</li>
<li>private methods (all private methods have a leading underscore)</li>
<li>public topic subscribers:<ul>
<li><a class="el" href="group___topics.html#gaa3fe8c6f5a98243c302c0d27cea219d9" title="subscriber topic to move servos in a physical position ">servos_absolute()</a></li>
<li><a class="el" href="group___topics.html#ga1262b2e51072c237c51b6de4cb199e53" title="subscriber topic to move servos in the range of ±1.0 ">servos_proportional()</a></li>
<li><a class="el" href="group___topics.html#gae257665eb64139d2720ed332e61507c6" title="subscriber topic to move servos based on a drive mode ">servos_drive()</a></li>
</ul>
</li>
<li>public services:<ul>
<li><a class="el" href="group___services.html#ga948cb0dd7ba8c2ac4c7f2d2d93940d85" title="service to set set PWM frequency ">set_pwm_frequency()</a></li>
<li>set_active_board()</li>
<li><a class="el" href="group___services.html#gabf512716d4497c6a4cb7bf9c5d94e2f1" title="store configuration data for servos on the active board ">config_servos()</a></li>
<li><a class="el" href="group___services.html#gae3222f92a0cd33b0d0a2fcfd6d563ba9" title="set drive mode and drive servos ">config_drive_mode()</a></li>
<li><a class="el" href="group___services.html#ga4583b417d172bde68e75db603da3362e" title="service to stop all servos on all boards ">stop_servos()</a></li>
</ul>
</li>
</ul>
<p>The code is currently authored in C and should be rewritten as proper C++.</p>
<p>This documentation refers to 'servo' and 'RC servo' but is equally applicable to any PWM or PPM controlled DC motor.</p>
<p>All published services and topics use a one-based count syntax. For example, the first servo is '1' and the default board is '1'. The hardware uses zero-based values. For example the first channel on the 16 channel 12-bit PWM board is '0' and the first I2C board is '0' with address 0x40. The switch from one-based to zero-based is done at the lowest level of this code. All public interactions should assume one-based values.</p>
<p><em>WARNING</em>: The code has only been tested with a single board using the default I2C address of 0x40. Once testing has been done with additional configurations, this warning will be removed or amended.</p>
<h1><a class="anchor" id="pwmservos"></a>
USING PWM WITH SERVOS</h1>
<p>While the PCA9685 chip and related boards are called "PWM" for pulse width modulation, there use with servos is more accurately PPM for pulse position modulation.</p>
<p>For standard 180 degree servos with a motion arc of ±90 degrees the pulse moves the servo arm to specifc position and holds it. For continuous motion servos, the pulse moves the servo at a specific speed.</p>
<p>The documentation will refer to positon, speed or position/speed. These are interchangeable as the two terms are dependent on whether the servo is a fixed rotation servo or a continuous rotation servo and independent of the board itself.</p>
<p>Analog RC servos are most often designed for 20ms pulses. This is achieved with a frequency of 50Hz. This software defaults to 50Hz. Use the set_pwm_frequncy() to change this frequency value. It may be necessary or convenient to change the PWM frequency if using DC motors connected to PWM controllers. It may also be convenient if using PWM to control LEDs.</p>
<p>A commonly available board is the Adafruit 16 channel 12-bit PWM board or the similarly named HAT. There are similar boards as well as clones. All of these boards use the PCA9685 chip. Not all boards have been tested.</p>
<p>The PWM boards drive LED and servos using pulse width modulation. The 12 bit interface means values are in the range of 0..4096. The pulse is defined as a start value and end value. When driving servos, the start point is typically 0 and the end point is the duration.</p>
<p>FYI: If using more than one PWM board or when using a board with an I2C address other than the default 0x40, the set_active_board() service must be used before using other services or topics from this package.</p>
<h1><a class="anchor" id="configuration"></a>
CONFIGURING SERVOS</h1>
<p>The tolerance of the resistors in RC servos means each servo may have a slightly different center point.</p>
<p>The <a class="el" href="group___topics.html#gaa3fe8c6f5a98243c302c0d27cea219d9" title="subscriber topic to move servos in a physical position ">servos_absolute()</a> topic controls servos with absolute pulse start and stop values. This topic subscriber is not generally useful in robot operations, however it is convenient for testing and for determining configuration values. Use this topic to determine the center position for a standard servo or the stop position for a continuous servo.</p>
<p>Also use this topic to determine the range of each servo - either the ±90 postion for a standard servo or the max forward and reverse speed for a continuous rotation servo.</p>
<p><b>note:</b> The centering value and range of servos is dependent on the pulse frequency. If you use <a class="el" href="group___services.html#ga948cb0dd7ba8c2ac4c7f2d2d93940d85" title="service to set set PWM frequency ">set_pwm_frequency()</a> to change the system value, you will need to determine new center and range values.</p>
<p>The <a class="el" href="group___topics.html#ga1262b2e51072c237c51b6de4cb199e53" title="subscriber topic to move servos in the range of ±1.0 ">servos_proportional()</a> topic controls servos through their range of motion using values between -1.0 and 1.0. Use the <a class="el" href="group___services.html#gabf512716d4497c6a4cb7bf9c5d94e2f1" title="store configuration data for servos on the active board ">config_servos()</a> service to set the center values, range values, and directions of rotation for servos. This enables servo motion to be generalized to a standard proportion of ±1.0. Use of the <a class="el" href="group___services.html#gabf512716d4497c6a4cb7bf9c5d94e2f1" title="store configuration data for servos on the active board ">config_servos()</a> service is required before proportional control is available.</p>
<h1><a class="anchor" id="drivemode"></a>
ROBOT DRIVE MODE</h1>
<p>In addition to absolute and proportional topics for controling servos, this package provides support for the geometry 'Twist' message. The <a class="el" href="group___topics.html#gae257665eb64139d2720ed332e61507c6" title="subscriber topic to move servos based on a drive mode ">servos_drive()</a> topic handles the calculations to convert linear and angular data to servo drive data.</p>
<p>Drive mode requires details for each servo. Use of the <a class="el" href="group___services.html#gabf512716d4497c6a4cb7bf9c5d94e2f1" title="store configuration data for servos on the active board ">config_servos()</a> before using drive mode.</p>
<p>The geometry_msgs::Twist providesf linear and angular velocity measured in m/s (meters per second) and r/s (radians per second) respectively. To perform the necessary calculations, data about the drive system is required. Use <a class="el" href="group___services.html#gae3222f92a0cd33b0d0a2fcfd6d563ba9" title="set drive mode and drive servos ">config_drive_mode()</a> to provide the RPM of the drive wheels, their radius, and the track distance between left and right. These values determine speed and turn rates.</p>
<p>Specifiy the desired drive mode with the <code>mode</code> property to cofig_drive_mode(). This package supports three drive modes:</p>
<ol type="1">
<li><b>ackerman</b> - A single velocity drive using one or more servos with a non-drive servo controlling steering.</li>
<li><b>differential</b> - Skid steer or track steer using one or more servos for each of the left and right sides. The result is full speed forward or reverse, min/max radius turns, and the ability to perform zero-radius turns</li>
<li><b>mecanum</b> - Independent drive on all four wheel capable of holonomic drive - moving in any combination of forward, reverse, turning, and sideways. The servos are assigned positons for left-front, right-front, left-rear, and right-rear wheels. This mode supports similar drive characteristics to differential drive with the additional of lateral motion.</li>
</ol>
<p>The servos on the PWM board are assigned to their respective drive positons using the <a class="el" href="group___services.html#gae3222f92a0cd33b0d0a2fcfd6d563ba9" title="set drive mode and drive servos ">config_drive_mode()</a> service. The applicable servos are assigned positions as follows:</p>
<table class="doxtable">
<tr>
<th>positon </th><th>ackerman </th><th>differential </th><th>mecanum  </th></tr>
<tr>
<td>position 1 corresponds to </td><td>drive </td><td>left </td><td>left-front </td></tr>
<tr>
<td>position 2 corresponds to </td><td></td><td>right </td><td>right-front </td></tr>
<tr>
<td>position 3 corresponds to </td><td></td><td></td><td>left-rear </td></tr>
<tr>
<td>position 4 corresponds to </td><td></td><td></td><td>right-rear </td></tr>
</table>
<p>The drive topic requires that use of both the <a class="el" href="group___services.html#gabf512716d4497c6a4cb7bf9c5d94e2f1" title="store configuration data for servos on the active board ">config_servos()</a> service and <a class="el" href="group___services.html#gae3222f92a0cd33b0d0a2fcfd6d563ba9" title="set drive mode and drive servos ">config_drive_mode()</a> service before drive mode will result in expected behavior.</p>
<p>All non-drive servos may still be operated with the proportion or absolute topics.</p>
<p><b>Note:</b> <em>This controller does not implement encoders for PWM motors. There is no guarantee that the drive velocity will exactly match the Twist message input. While this may not be acceptable for a commercial or scientific application, it may not be of convern for education and amatuer competitions. Encoders could be added and feedback applied to the PWM values. Additionally, when drive control is a product of positional feedback - such as line following and navigation via camera vision - drive encoders are usually not required.</em></p>
<p>The <a class="el" href="group___services.html#ga4583b417d172bde68e75db603da3362e" title="service to stop all servos on all boards ">stop_servos()</a> service is provided as convenience to stop all servos and place then is a powered off state. This is different from setting each servo to its center value. The stop service is useful as a safety operation.</p>
<h1><a class="anchor" id="testing"></a>
TESTING</h1>
<p>Basic testing is available from the command line. Start the I2C PWM node with <code>roslaunch i2cpwm_board i2cpwm_node.launch</code> (or <code>roscore</code> and <code>rosrun i2cpwm_board i2cpwm_board</code>) and then proceed with example commands contained within the documentation for each service and topic subscriber. </p>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.11-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.11
</small></address>
</body>
</html>
